package guiclient;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.*;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

public class GUIClient extends JFrame {
    final List<OrderTableBean> orderTableBeen = new ArrayList<OrderTableBean>();
    private  final Client client = new Client(orderTableBeen);

    public GUIClient() {

        final TableModel model = new MyTableModel(orderTableBeen);
        final JTable table = new JTable(model);
        table.setDefaultRenderer(Object.class, new MyRenderer(orderTableBeen));
        final JScrollPane jspTable = new JScrollPane(table);
        jspTable.setEnabled(false);

        String[] items = {"BUY", "SALE"};
        final JComboBox<String> jcbType = new JComboBox<String>(items);
        jcbType.setEnabled(false);

        final JLabel jlUsername = new JLabel("Username");
        final JTextField jtfUsername = new JTextField();
        final JButton jbLogin = new JButton("Login");

        final JLabel jlType = new JLabel("Type");
        jlType.setEnabled(false);
        final JLabel jlStock = new JLabel("Stock");
        jlStock.setEnabled(false);
        final JTextField jtfStock = new JTextField();
        jtfStock.setEnabled(false);
        final JLabel jlPrice = new JLabel("Price");
        jlPrice.setEnabled(false);
        final JTextField jtfPrice = new JTextField();
        jtfPrice.setEnabled(false);
        final JLabel jlSize = new JLabel("Size");
        jlSize.setEnabled(false);
        final JTextField jtfSize = new JTextField();
        jtfSize.setEnabled(false);
        final JButton jbSend = new JButton("Send");
        jbSend.setEnabled(false);

        jbLogin.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                client.sendAuthMessage(jtfUsername.getText());
                boolean authAnswer = false;
                do {
                    try {
                        authAnswer = client.receiveAuthMessage();
                    } catch (AuthClientException e1) {
                        JOptionPane.showMessageDialog(null, e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                        return;
                    }
                } while (!authAnswer);
                jlUsername.setEnabled(false);
                jtfUsername.setEnabled(false);
                jbLogin.setEnabled(false);
                jspTable.setEnabled(true);
                jcbType.setEnabled(true);
                jlType.setEnabled(true);
                jlPrice.setEnabled(true);
                jtfPrice.setEnabled(true);
                jlStock.setEnabled(true);
                jtfStock.setEnabled(true);
                jlSize.setEnabled(true);
                jtfSize.setEnabled(true);
                jbSend.setEnabled(true);
                (new Thread(client)).start();
                (new Thread(new Runnable() {
                    @Override
                    public void run() {
                        table.revalidate();
                    }
                })).start();
            }
        });

        jbSend.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                client.setFill(false);
                client.sendOrder(jcbType.getSelectedItem().toString(),
                        jtfStock.getText(), jtfPrice.getText(),
                        jtfSize.getText());
                long orderId = -1;
                do {
                    try {
                        orderId = client.receiveOrderMessage();
                    } catch (AddOrderException e1) {
                        JOptionPane.showMessageDialog(null, e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                        return;
                    }
                } while (orderId < 0);
                Double price = Double.parseDouble(jtfPrice.getText());
                int size = Integer.parseInt(jtfSize.getText());
                orderTableBeen.add(new OrderTableBean(orderId,
                        jcbType.getSelectedItem().toString(),
                        jtfStock.getText(), price,
                        size, size));
                client.setFill(true);
            }
        });

        GroupLayout layout = new GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);

        layout.setHorizontalGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                        .addComponent(jlUsername)
                        .addComponent(jtfUsername)
                        .addComponent(jbLogin)
                        .addComponent(jlType)
                        .addComponent(jcbType)
                        .addComponent(jlStock)
                        .addComponent(jtfStock)
                        .addComponent(jlPrice)
                        .addComponent(jtfPrice)
                        .addComponent(jlSize)
                        .addComponent(jtfSize)
                        .addComponent(jbSend))
                .addComponent(jspTable));

        layout.setVerticalGroup(layout.createParallelGroup()
                .addGroup(layout.createSequentialGroup()
                        .addComponent(jlUsername)
                        .addComponent(jtfUsername)
                        .addComponent(jbLogin)
                        .addComponent(jlType)
                        .addComponent(jcbType)
                        .addComponent(jlStock)
                        .addComponent(jtfStock)
                        .addComponent(jlPrice)
                        .addComponent(jtfPrice)
                        .addComponent(jlSize)
                        .addComponent(jtfSize)
                        .addComponent(jbSend))
                .addComponent(jspTable));

        setPreferredSize(new Dimension(680, 360));
        setTitle("GUI Client");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        pack();
        setVisible(true);

        client.connect();
    }

    public class MyTableModel implements TableModel {
        private Set<TableModelListener> listeners = new HashSet<TableModelListener>();
        private List<OrderTableBean> beans;

        public MyTableModel(List<OrderTableBean> beans) {
            this.beans = beans;
        }

        public void addTableModelListener(TableModelListener listener) {
            listeners.add(listener);
        }

        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        public int getColumnCount() {
            return 5;
        }

        public String getColumnName(int columnIndex) {
            switch (columnIndex) {
                case 0:
                    return "Id";
                case 1:
                    return "Тип";
                case 2:
                    return "Акции";
                case 3:
                    return "Цена";
                case 4:
                    return "Колличество";
                case 5:
                    return "Остаток";
            }
            return "";
        }

        public int getRowCount() {
            return beans.size();
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            OrderTableBean bean = beans.get(rowIndex);
            switch (columnIndex) {
                case 0:
                    return bean.getId();
                case 1:
                    return bean.getType();
                case 2:
                    return bean.getStock();
                case 3:
                    return bean.getPrice();
                case 4:
                    return bean.getSize();
                case 5:
                    return bean.getRemainderSize();
            }
            return "";
        }

        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return false;
        }

        public void removeTableModelListener(TableModelListener listener) {
            listeners.remove(listener);
        }

        public void setValueAt(Object value, int rowIndex, int columnIndex) {
        }

    }

    public class MyRenderer implements TableCellRenderer {
        List<OrderTableBean> beens;

        MyRenderer(List<OrderTableBean> table) {
            this.beens = table;
        }

        @Override
        public Component getTableCellRendererComponent(JTable table,
                                                       Object value,
                                                       boolean isSelected,
                                                       boolean hasFocus,
                                                       int row, int column) {
            JTextField editor = new JTextField();
            OrderTableBean been =  beens.get(row);
            if (value != null) {
                editor.setText(value.toString());
            }

            if (been.getRemainderSize() == 0) {
                editor.setBackground(Color.decode("#00CC99"));
            } else if (been.getRemainderSize() < been.getSize()) {
                editor.setBackground(Color.decode("#33FFCC"));
            }
            return editor;
        }
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new GUIClient();
            }
        });
    }

}